/*
    SEL - Simple DirectMedia Layer Extension Library
    Copyright (C) 2001 Matej Knopp <knopp@users.sf.net>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#ifndef __sel_object_h__
#define __sel_object_h__

#include "debug.h"

namespace SEL
{

//! An object with reference counting abilities.
class Object
{
public:
        //! Default constructor. 
	/*! 
	  This sets the number of references to 1.
         */
        Object ();

        //! Default destructor. 
	/*!
	  You shouldn't call this directly or free the object directly. 
	  Instead of that you should call the unref member function.
	  \sa unref
         */
        virtual ~Object ();

        //! Increase the number of references and return it.
        int ref ();

        //! Decrease the number of references.
        void unref ();

        //! Return the number of references.
        int getRef ();

        //! Safer alternative of the ref() function.
	/*! 
	  If you call this with the object = NULL the program
          won't crash as if it would if you called object->ref().
          Instead of that this would write a warning.
         
          \param object
          \sa ref()
         */
        static int ref (Object *object);

        //! Safer alternative of the unref() function. 
	/*!
	 See ref(object) for more detailed description.
         
	 \param object
         \sa unref()
         \sa ref(object)
         */
	// TODO: ZAP! (template&reference)
	static void unref (Object *object);

protected:
	int m_ref;
}; // class Object

//////////////////////////////////////////////////////////////
/////////////////////  INLINE FUNCTIONS  /////////////////////
//////////////////////////////////////////////////////////////

inline
Object::Object ()
{
	m_ref = 1;
}

inline
Object::~Object ()
{
	if (m_ref != 0) {
		warning ("Destroying object with ref. count " << m_ref << "!");
        }
}

inline int
Object::ref ()
{
        return ++m_ref;
}

inline void
Object::unref ()
{
        --m_ref;
        s_assert (m_ref >= 0);
        if (m_ref <= 0) {
                delete (this);
        }
}

inline int
Object::getRef ()
{
	return m_ref;
}

inline int
Object::ref (Object *object)
{
	if (object)
        	return object->ref ();
	warning ("Trying to ref (null) object!");
        return 0;
}

inline void
Object::unref (Object *object)
{
	if (object)
        	return object->unref ();
	warning ("Trying to unref (null) object!");
}

} // namespace SEL

#endif // __sel_object_h__

